package com.example.opengl.custombuttom;

import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.BoringLayout;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.MeasureSpec;
import android.widget.TextView;

public class CustomButton extends View {

    private static final String TAG = "CustomButton"; 

    private CharSequence mText = null;
    private StaticLayout mLayout;
    private final TextPaint mTextPaint;
    private ColorStateList mTextColorList;
    private int mCurTextColor;
    private int mTextLayoutWidth;
    private int mTextWidth;
    private int mTextHeight;

    private int mPaddingTop;
    private int mPaddingBottom;
    private int mPaddingLeft;
    private int mPaddingRight;

    private Drawable mDrawableLeft;
    private int mDrawablePadding;
    private int mDrawableWidth;
    private int mDrawableHeight;

    private int AnlignPaddingTextLeft;
    private int AnlignPaddingTextTop;
    private int AnlignPaddingDrawableLeft;
    private int AnlignPaddingDrawableTop;   

    private TextView end;
    
    public CustomButton(Context context) {
        this(context, null);
        Log.i(TAG,"CustomButton("+context+")");
    }

    public CustomButton(Context context,AttributeSet attrs) {        
        this(context,attrs,0);        
        Log.i(TAG,"CustomButton("+context+","+attrs+")");    
    }

    public CustomButton(Context context,AttributeSet attrs,int defStyle) {        
        super(context,attrs,defStyle);        

        mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.density = getResources().getDisplayMetrics().density;

        init_variable();
        
        int[] ids = new int[attrs.getAttributeCount()];
        for (int i = 0; i < attrs.getAttributeCount(); i++) {
            ids[i] = attrs.getAttributeNameResource(i);
        }
        
        TypedArray a = context.obtainStyledAttributes(attrs, ids, defStyle, 0);

        for (int i = 0; i < attrs.getAttributeCount(); i++) {
            String attrName = attrs.getAttributeName(i);
            if (attrName == null)
                continue;
            
            if (attrName.equals("text")) {
                mText = a.getText(i);
            }
            else if (attrName.equals("textColor")) {
                ColorStateList color = a.getColorStateList(i);
                setTextColorStateList(color);
            }
            else if (attrName.equals("textSize")) {
                int textSize = a.getDimensionPixelSize(i, 15);
                setRawTextSize(textSize);
            }
            else if (attrName.equals("drawableLeft")) {
                Drawable d = a.getDrawable(i);
                setButtonDrawable(d);
            }
            else if (attrName.equals("drawablePadding")) {
                mDrawablePadding = a.getDimensionPixelSize(i, 0);
            }
        }
        
        a.recycle();
        Log.i(TAG,"CustomButton("+context+","+attrs+","+defStyle+"),text:"+mText);
    }

    private void init_variable(){
        mPaddingTop = 0;
        mPaddingBottom = 0;
        mPaddingLeft = 0;
        mPaddingRight = 0;
        
        mText = null;
        mTextColorList = null;
        mCurTextColor = Color.WHITE;
        mTextWidth = 0;
        mTextHeight = 0;

        mDrawableLeft = null;
        mDrawablePadding = 0;
        mDrawableWidth = 0;
        mDrawableHeight = 0;
        
        AnlignPaddingTextLeft = 0;
        AnlignPaddingTextTop = 0;
        AnlignPaddingDrawableLeft = 0;
        AnlignPaddingDrawableTop = 0;
    }

    private void setButtonDrawable(Drawable d) {
        if (d != null) {
            if (mDrawableLeft != null) {
                mDrawableLeft.setCallback(null);
                unscheduleDrawable(mDrawableLeft);
            }

            d.setCallback(this);
            d.setState(getDrawableState());
            d.setVisible(getVisibility() == VISIBLE, false);

            mDrawableLeft = d;
            mDrawableLeft.setState(null);
            
            mDrawableWidth = mDrawableLeft.getIntrinsicWidth();
            mDrawableHeight = mDrawableLeft.getIntrinsicHeight();

            setMinimumHeight(mDrawableHeight);
            mDrawableLeft.setBounds(0, 0, mDrawableWidth, mDrawableHeight);

            refreshDrawableState();
        }
    }

    private void setRawTextSize(float size) {
        if (size != mTextPaint.getTextSize()) {
            mTextPaint.setTextSize(size);
        }
    }

    private void setTextColorStateList(ColorStateList color) {
        if (color != null) {
            mTextColorList = color;
        }
        updateTextColors();
    }

    private void updateTextColors() {
        boolean inval = false;
        int color = mTextColorList.getColorForState(getDrawableState(), 0);
        if (color != mCurTextColor) {
            mCurTextColor = color;
            inval = true;
        }

        if (inval) {
            invalidate();
        }
    }

    @Override    
    protected void onFinishInflate() {        
        setClickable(true);        
        Log.i(TAG,"onFinishInflate()");    
    }

    @Override    
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int width;
        int height;

        mPaddingTop = getPaddingTop();
        mPaddingBottom = getPaddingBottom();
        mPaddingLeft = getPaddingLeft();
        mPaddingRight = getPaddingRight();

        if(widthMode == MeasureSpec.EXACTLY){
            width = widthSize;
        } else {
            int des = (int) FloatMath.ceil(Layout.getDesiredWidth(mText, mTextPaint));
            width = mPaddingLeft + mDrawableWidth + mDrawablePadding + des + mPaddingRight;  

            // Check against our minimum width
            width = Math.max(width, getSuggestedMinimumWidth());

            if (widthMode == MeasureSpec.AT_MOST) {
                width = Math.min(widthSize, width);
            }            
        }

        int want = width - mPaddingLeft - mDrawableWidth - mDrawablePadding - mPaddingRight;
        if(want <= 0){
            mLayout = null;
            mTextWidth = 0;
            mTextLayoutWidth = 0;
        } else {
            if (mLayout == null || mTextLayoutWidth != want) {
                mTextLayoutWidth = want;
                mLayout = new StaticLayout(mText, mTextPaint, mTextLayoutWidth, Layout.Alignment.ALIGN_CENTER, 1, 0, false);

                int lineCount = mLayout.getLineCount();
                int lineWidth = 0;
                for(int i = 0 ; i < lineCount ; i++){
                    int lintCountWidth = (int) FloatMath.ceil(mLayout.getLineWidth(i)); 
                    lineWidth = Math.max(lineWidth, lintCountWidth);            
                }

                if (mTextLayoutWidth != lineWidth){
                    mLayout = new StaticLayout(mText, mTextPaint, lineWidth, Layout.Alignment.ALIGN_CENTER, 1, 0, false);
                    mTextWidth = lineWidth;
                } else {
                    mTextWidth = mTextLayoutWidth;
                }
            }            
        }

        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            height = getDesiredHeight(mLayout);

            if (heightMode == MeasureSpec.AT_MOST) {
                height = Math.min(height, heightSize);
            }
        }

        setMeasuredDimension(widthSize, heightSize);
        Log.i(TAG,"setMeasuredDimension "+widthSize+" / "+heightSize); 
    }

    private int getDesiredHeight(Layout layout) {
        if (layout == null) {
            return 0;
        }

        int linecount = layout.getLineCount();
        int pad = mPaddingTop + mPaddingBottom;
        int desired = layout.getLineTop(linecount);

        mTextHeight = desired;
        
        desired = Math.max(desired, mDrawableHeight);
        desired += pad;

        // Check against our minimum height
        desired = Math.max(desired, getSuggestedMinimumHeight());

        return desired;
    }

    @Override    
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        Log.i(TAG,"onLayout("+changed+","+left+","+top+","+right+","+bottom+")");

        int width = right-left;
        int height = bottom-top;
        Log.i(TAG,"onLayout(left-right = "+width+" , getWidth() = "+ getWidth()+")");
        Log.i(TAG,"onLayout(top-bottom = "+height+" , getWidth() = "+ getHeight()+")");

        int AnlignCenterPaddingWidth = (getWidth() - mPaddingLeft - mDrawableWidth - mDrawablePadding - mTextWidth - mPaddingRight)/2;
        AnlignPaddingTextLeft = AnlignCenterPaddingWidth + mPaddingLeft + mDrawableWidth + mDrawablePadding;
        AnlignPaddingDrawableLeft = AnlignCenterPaddingWidth + mPaddingLeft;

        int AnlignCenterPaddingHeight = (getHeight() - mPaddingTop - mPaddingBottom);
        AnlignPaddingTextTop = (AnlignCenterPaddingHeight - mTextHeight)/2;
        AnlignPaddingDrawableTop = (AnlignCenterPaddingHeight - mDrawableHeight)/2;
        Log.i(TAG,"onLayout("+AnlignCenterPaddingWidth+","+AnlignCenterPaddingHeight+")");        
        Log.i(TAG,"onLayout("+AnlignPaddingTextLeft+","+AnlignPaddingTextTop+","+AnlignPaddingDrawableLeft+","+AnlignPaddingDrawableTop+")");
    }

    @Override    
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        Log.i(TAG,"onSizeChanged("+w+","+h+","+oldw+","+oldh+")");    
    }

    @Override    
    protected void onDraw(Canvas canvas) {        
        super.onDraw(canvas);

        if (mText != null && mLayout != null ) { 
            canvas.save();
            canvas.translate(AnlignPaddingTextLeft , AnlignPaddingTextTop);
            mTextPaint.setColor(mCurTextColor);
            mLayout.draw(canvas);
            canvas.restore();
        }

        if (mDrawableLeft != null) {
            canvas.save();
            canvas.translate(AnlignPaddingDrawableLeft , AnlignPaddingDrawableTop);
            mDrawableLeft.draw(canvas);
            canvas.restore();
        }
        Log.i(TAG,"onDraw("+canvas+")");    
    }

    @Override
    public void setSelected(boolean selected) {
        super.setSelected(selected);
    }
    
    @Override    
    public boolean onTouchEvent(MotionEvent event) {        
        Log.i(TAG,"onTouchEvent("+event+")");        
        switch(event.getAction()) {        
            case MotionEvent.ACTION_UP:                
                break;        
            case MotionEvent.ACTION_DOWN:            
                break;        
            case MotionEvent.ACTION_MOVE:            
                break;        
        }        
       
        return super.onTouchEvent(event);    
     }

    @Override
    protected void drawableStateChanged() {
        Log.i(TAG,"drawableStateChanged");
        super.drawableStateChanged();

        if (mTextColorList != null && mTextColorList.isStateful()) {
            updateTextColors();
        }

        if (mDrawableLeft != null && mDrawableLeft.isStateful()) {
            int[] state = getDrawableState();
            mDrawableLeft.setState(state);
        }
    }

    @Override
    protected boolean verifyDrawable(Drawable who) {
        Log.i(TAG,"verifyDrawable("+who+")");      
        return super.verifyDrawable(who) || who == mDrawableLeft;
    }
}

